﻿using Domain.Entities.Audit;
using Domain.Entities;
using Infrastructure.Persistence.Extensions;
using System.Reflection;
using Domain.Entities.Loggers;
using Domain.Entities.Organizations;
using Domain.Entities.Tenants;
using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
using Common.Enums;
using Domain.Services;

namespace Infrastructure.Persistence;

#nullable disable

public class ApplicationDbContext : DbContext, IApplicationDbContext
{
    private readonly MultiTenancyService _multiTenantService;
    public ApplicationDbContext(
     DbContextOptions<ApplicationDbContext> options,
     MultiTenancyService multiTenantService) : base(options)
    {
        _multiTenantService = multiTenantService;
    }

    public DbSet<User> Users { get; set; }
    public DbSet<AuditTrail> AuditTrails { get; set; }
    public DbSet<Logger> Loggers { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<UserRole> UserRoles { get; set; }
    public DbSet<Menu> Menus { get; set; }
    public DbSet<RoleMenu> RoleMenus { get; set; }
    public DbSet<Organization> Organizations { get; set; }
    public DbSet<Tenant> Tenants { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
        if (_multiTenantService.IsEnabled())
        {
            string tenantId = _multiTenantService.GetCurrentTenantId();
            //builder.ApplyGlobalFilters<ISoftDelete, ITenant>(
            //        s => s.Deleted == null, // 软删除过滤器
            //        t => t.TenantId == tenantId);// 租户过滤器
            builder.ApplyGlobalFilters<ISoftDelete>(s => s.Deleted == null);
        }
        else 
        {
            builder.ApplyGlobalFilters<ISoftDelete>(s => s.Deleted == null);
        }
    }

    protected override  void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (_multiTenantService.IsEnabled() == false) return;
        if (_multiTenantService.IsUseDefaultConnectionString()) return;
        if (_multiTenantService.IsTenantDefault()) return;

        var tenant = _multiTenantService.GetCurrentTenant();
        if (tenant?.IsolationType == MultiTenancyIsolationType.DatabaseIsolation) 
        {
            switch (tenant.DbProviderType)
            {
                case DbProviderType.Sqlite:
                    optionsBuilder.UseSqlite(tenant.ConnectionString);
                    break;
                case DbProviderType.MySql:
                    optionsBuilder.UseMySql(tenant.ConnectionString, ServerVersion.Create(new Version(8, 0, 26), ServerType.MySql));
                    break;
                case DbProviderType.MsSql:
                    optionsBuilder.UseSqlServer(tenant.ConnectionString);
                    break;
                case DbProviderType.PostgreSql:
                    optionsBuilder.UseNpgsql(tenant.ConnectionString);
                    break;
                default:
                    throw new NotSupportedException($"Unsupported database provider type: {tenant.DbProviderType}");
            }
        }
    }

    public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        return base.SaveChangesAsync(cancellationToken);
    }
}
